/*
 * @author Kansas
 * ICS314 Sundial Project
 *
 * A component that contains a gnomon and a dial plate with hour lines drawn
 * based on the sundialCalculations.
 *
 */

import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.util.ArrayList;
import javax.swing.*;

public class SundialFace extends JFrame implements Printable{
       
        int     panelHeight;
        int     panelWidth;
        double  margin;
        boolean passed; // Notes if variables were passed
        
        //Need the gnomon length
        double  gnomonLength;
       
        //Fields for the dial plate
        double  hourLineOriginX;
        double  hourLineOriginY;
               
        double  hourLineEndX;
        double  hourLineEndY;
       
        // Normal range: 6:00 - 18:00
        // DST range: 7:00 - 19:00
        int                             currentHour;
        boolean                         DST;
        ArrayList<Double>       hourAngles;
       
        /*
         * Default Constructor
         */
        public SundialFace(){
            //default; should never execute
        setTitle("Face Error");
        setSize(400, 400);
        setVisible(true);
        setBackground(Color.white);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        passed = false;
        }
       
        /*
         * Constructor:
         * Creates a new SundialOutput and sets its dimensions,
         * the origin and end coordinates of the gnomon base and
         * latitude angle lines, and the origins for the dial plate's
         * hour lines.
         *
         * @param height
         *              The height of the SundialOutput component.
         *              Its width will be set to double this value.
         *              Must be at least 500.
         *
         * @param latitude
         *              The latitude that has been input by the user.
         *              Used to draw the gnomon.
         *              Must be in the 10-80 range.
         *
         *
         * @param angles
         *              The ArrayList containing the angles of the hour lines
         *              to be drawn. Must contain 13 angles, for the hours
         *              6:00-18:00.
         *
         * @param daylight
         *              Whether or not daylight saving is in effect.
         */
        public SundialFace(int height, double latitude, ArrayList<Double> angles, boolean daylight) throws Exception{
        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
        setTitle("Sundial Face");
        setSize(size);
        setVisible(true);
        setBackground(Color.white);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
               
                if(height < 500){
                        throw new Exception("Height must be at least 500");
                }
                if((latitude < 10.0) || (latitude > 80.0)){
                        throw new Exception ("Latitude must be in the range 10 - 80");
                }
                if(angles == null){
                        throw new Exception ("ArrayList cannot be null");
                }
                if(angles.size() != 13){
                        throw new Exception ("ArrayList has wrong number of angles");
                }
               
                panelHeight             = height;
                panelWidth              = 2*height;
              
               
                DST                     = daylight;
                hourAngles              = angles;
               
                gnomonLength    = panelWidth/5.0;
               
                //Where the face is drawn
                hourLineOriginX = 275;
                hourLineOriginY = 275;
               
                passed                  = true;
        }
       
       
        /*
         * Loop that draws and labels all hour angles from the given ArrayList
         *      based on military time.
         * Negative angles draw lines left of the origin, while positive angles
         *      draw lines right of the origin.
         *
         * @param target
         *              The Graphics2D on which to draw the angles.
         * @param angles
         *              The ArrayList containing the hour angles to draw.
         */
        public void drawHourAngles(Graphics2D target, ArrayList<Double> angles){                
                for (int i = 0; i < angles.size(); i++){
	                hourLineEndX = hourLineOriginX + gnomonLength * Math.sin(Math.toRadians(angles.get(i)));
	                hourLineEndY = hourLineOriginY - gnomonLength * Math.cos(Math.toRadians(angles.get(i)));
	                target.draw(new Line2D.Double(hourLineOriginX, hourLineOriginY, hourLineEndX, hourLineEndY));
	                target.drawString(Integer.toString(currentHour), (int) hourLineEndX, (int) hourLineEndY);
	                currentHour++;
                }
        }
       
       
        public void paint (Graphics gr){
                Graphics2D gr2d = (Graphics2D) gr;
               
                setBackground(Color.white);
                gr2d.setColor(Color.black);
                if(passed){
                                                               
                        gr2d.setColor(Color.black);
               
                        if (DST)
                                currentHour = 7;
                        else
                                currentHour = 6;
               
                        drawHourAngles(gr2d, hourAngles);
                                       
                        //line on which to place gnomon (draw last, in red)
                        gr2d.setColor(Color.red);
                        gr2d.draw(new Line2D.Double(hourLineOriginX, hourLineOriginY, hourLineOriginX, hourLineOriginY - gnomonLength));
                        gr2d.drawString("N", (int) hourLineOriginX, (int) (hourLineOriginY - gnomonLength - 30));              
                        //System.out.println("Painting");//Testing purposes
                }else{
                        gr2d.drawString("Hours array is null", 150, 200);
                }
        }

       
        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
                        throws PrinterException {

        // Only one page, should not be any more
        // Prevents the infinite printing problem
        if (pageIndex > 0) {
            return NO_SUCH_PAGE;
        }

        // X and Y values are to ensure that the entire area is printed
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        // Rendering
        this.paint(g2d);

        // This page exists
        return PAGE_EXISTS;

        }


}



